[bits 32]

	MULTIBOOT_PAGE_ALIGN   equ 1<<0
	MULTIBOOT_MEMORY_INFO  equ 1<<1

	MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
	MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO
	CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)

	align 4
        dd MULTIBOOT_HEADER_MAGIC
        dd MULTIBOOT_HEADER_FLAGS
        dd CHECKSUM

DATA_MAGIC	equ	0x3544DA2A

[section .text]

extern	kmain
extern	kbasic_error
extern	KCODE32
extern	KDATA32
extern	KTSS_SEL
global	force_end
global _start

_start:
	call	where	
	where:
	pop	esi
	sub	esi, where	; ESI contem a diferença entre endereço fisico e virtual!
	cmp	dword [ds_check + esi], DATA_MAGIC	; Segmento de dados esta correto?
	jne	short $
	mov	[virt2phys + esi], esi			; Armazena ESI em variavel de conversão.
	sub	ebx,esi
	mov	[mbi + esi], ebx
	mov	ecx,esi
	shr	ecx,16

	; Atualiza endereço base nos descritores da GDT

	add	[gdt_kcode + 2 + esi],si
	adc	[gdt_kcode + 4 + esi],cl
	adc	[gdt_kcode + 7 + esi],ch
	add	[gdt_kdata + 2 + esi],si
	adc	[gdt_kdata + 4 + esi],cl
	adc	[gdt_kdata + 7 + esi],ch
	add	[gdt_ptr + 2 + esi],esi

	lgdt	[gdt_ptr + esi]
	jmp	KERNEL_CS:continua
continua:
	mov	cx,KERNEL_DS
	mov	ds,ecx
	mov	ss,ecx
	mov	es,ecx
	mov	fs,ecx
	mov	gs,ecx
	mov	esp, pilha
	push	dword 2
	popf
	mov	cx, word KERNEL_CS
	mov	[KCODE32], cx
	mov	cx, word KERNEL_DS
	mov	[KDATA32], cx
	mov	cx, TSS_SELECTOR
	mov	[KTSS_SEL], cx
	push	eax
	call	kmain
	push	eax
	call	kbasic_error
force_end:
	cli
	hlt
	.1
	jmp	.1

extern	isr_divide_error
global	isr0
isr0:
	pusha
	push	gs
	push	fs
	push	ds
	push	es

	call	isr_divide_error

	pop	es
	pop	ds
	pop	fs
	pop	gs
	popa
	iret

extern	isr_ex_dep
global	isr1
isr1:
	pusha
	push	gs
	push	fs
	push	ds
	push	es

	call	isr_ex_dep

	pop	es
	pop	ds
	pop	fs
	pop	gs
	popa
	iret

extern	isr_page_fault
global	isr14
isr14:
	pusha
	push	gs
	push	fs
	push	ds
	push	es
	mov	eax, cr3
	push	eax

	call	isr_page_fault

	pop	es
	pop	ds
	pop	fs
	pop	gs
	popa
	iret

global	irq0
irq0:
	cli
	push	byte 0	; ISR sem código de erro
	push	byte 32
	jmp	irq_common
	
global	irq1
irq1:
	cli
	push	byte 0	; ISR sem código de erro
	push	byte 33
	jmp	irq_common


extern	irq_common_callback
irq_common:
    pusha
    push ds
    push es
    push fs
    push gs
    mov ax, 0x10
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov eax, esp
    push eax		; Numero da IRQ na pilha
    mov eax, irq_common_callback
    call eax
    pop eax
    pop gs
    pop fs
    pop es
    pop ds
    popa
    add esp, 8
    iret

[section .data]

ds_check:
		dd	DATA_MAGIC
global	virt2phys
virt2phys	dd	0

gdt:
	dw 0		; limit 15:0
	dw 0		; base 15:0
	db 0		; base 23:16
	db 0		; type
	db 0		; limit 19:16, flags
	db 0		; base 31:24
KERNEL_CS equ ($-gdt)
gdt_kcode:
	dw 0xFFFF
	dw 0
	db 0
	db 0x9A	; present, ring 0, code, non-conforming, readable
	db 0xCF
	db 0
KERNEL_DS equ ($-gdt)
gdt_kdata:
	dw 0xFFFF
	dw 0
	db 0
	db 0x92	; present, ring 0, data, expand-up, writable
	db 0xCF
	db 0
TSS_SELECTOR EQU ($-gdt)
gdt_tss:
	dw 103
	dw 0
	db 0
	db 0x89	; present, ring 0, available 32-bit TSS
	db 0
	db 0
gdt_end:

gdt_ptr:
	dw gdt_end - gdt - 1
	dd gdt

global	tss
global	tss_esp0
tss:
	dw 0, 0	; back link
tss_esp0:
	dd 0		; ESP0
	dw KERNEL_DS, 0	; SS0, reserved

	dd 0		; ESP1
	dw 0, 0		; SS1, reserved

	dd 0		; ESP2
	dw 0, 0		; SS2, reserved

	dd 0		; CR3
	dd 0, 0		; EIP, EFLAGS
	dd 0, 0, 0, 0	; EAX, ECX, EDX, EBX
	dd 0, 0, 0, 0	; ESP, EBP, ESI, EDI
	dw 0, 0		; ES, reserved
	dw 0, 0		; CS, reserved
	dw 0, 0		; SS, reserved
	dw 0, 0		; DS, reserved
	dw 0, 0		; FS, reserved
	dw 0, 0		; GS, reserved
	dw 0, 0		; LDT, reserved
	dw 0, 104	; debug, IO permission bitmap (none)


[section .bss]

align	4096
	resd	1023

pilha:
global	mbi
	mbi	resd	1
